// ========================================== // 1. SUPABASE CLIENT & INITIALIZATION // ========================================== const SUPABASE_URL = "https://gaexgnlfybkyrskuklye.supabase.co"; const SUPABASE_ANON_KEY = "sb_publishable_brGGq6blboMQRehfL54hEw_n3HRFhRV"; // Global client definition avoiding redeclaration const supabaseClient = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY); // State Management let currentUser = null; let currentProfile = null; let activeDMUser = null; let messageSubscription = null; // ========================================== // 2. DOM ELEMENTS // ========================================== const authScreen = document.getElementById("authScreen"); const appMount = document.getElementById("appMount"); const authForm = document.getElementById("authForm"); const tabLogin = document.getElementById("tabLogin"); const tabRegister = document.getElementById("tabRegister"); const usernameFieldGroup = document.getElementById("usernameFieldGroup"); const authUsername = document.getElementById("authUsername"); const authEmail = document.getElementById("authEmail"); const authPassword = document.getElementById("authPassword"); const authError = document.getElementById("authError"); const authSubmitBtn = document.getElementById("authSubmitBtn"); // Main App UI const friendsList = document.getElementById("friendsList"); const myPanelAvatar = document.getElementById("myPanelAvatar"); const myPanelDefaultAvatar = document.getElementById("myPanelDefaultAvatar"); const myPanelDisplayName = document.getElementById("myPanelDisplayName"); const myPanelTag = document.getElementById("myPanelTag"); // Chat & Views const chatView = document.getElementById("chatView"); const nitroView = document.getElementById("nitroView"); const navFriends = document.getElementById("navFriends"); const navNitro = document.getElementById("navNitro"); const activeDMTitle = document.getElementById("activeDMTitle"); const messagesContainer = document.getElementById("messagesContainer"); const messageInput = document.getElementById("messageInput"); const sendBtn = document.getElementById("sendBtn"); // Modals const settingsModal = document.getElementById("settingsModal"); const openSettingsBtn = document.getElementById("openSettingsBtn"); const closeSettingsBtn = document.getElementById("closeSettingsBtn"); const addFriendModal = document.getElementById("addFriendModal"); const openAddFriendModal = document.getElementById("openAddFriendModal"); const closeAddFriendBtn = document.getElementById("closeAddFriendBtn"); const submitAddFriendBtn = document.getElementById("submitAddFriendBtn"); const addFriendUsername = document.getElementById("addFriendUsername"); const addFriendError = document.getElementById("addFriendError"); // Profile Edit Elements const editDisplayName = document.getElementById("editDisplayName"); const editPronouns = document.getElementById("editPronouns"); const editBio = document.getElementById("editBio"); const editAvatarUrl = document.getElementById("editAvatarUrl"); const editBannerUrl = document.getElementById("editBannerUrl"); const saveProfileBtn = document.getElementById("saveProfileBtn"); // Preview Elements const previewAvatar = document.getElementById("previewAvatar"); const previewDefaultAvatar = document.getElementById("previewDefaultAvatar"); const previewBanner = document.getElementById("previewBanner"); const previewDisplayName = document.getElementById("previewDisplayName"); const previewUsername = document.getElementById("previewUsername"); const previewPronouns = document.getElementById("previewPronouns"); const previewBio = document.getElementById("previewBio"); // Appearance Controls const appBgInput = document.getElementById("appBgInput"); const glassOpacityRange = document.getElementById("glassOpacityRange"); const glassBlurRange = document.getElementById("glassBlurRange"); const opacityVal = document.getElementById("opacityVal"); const blurVal = document.getElementById("blurVal"); const applyAppearanceBtn = document.getElementById("applyAppearanceBtn"); let isRegistering = false; // ========================================== // 3. AUTHENTICATION & SESSION // ========================================== tabLogin.addEventListener("click", () => setAuthMode(false)); tabRegister.addEventListener("click", () => setAuthMode(true)); function setAuthMode(register) { isRegistering = register; authError.textContent = ""; if (register) { tabRegister.classList.add("active"); tabLogin.classList.remove("active"); usernameFieldGroup.classList.remove("hidden"); authSubmitBtn.textContent = "Register"; } else { tabLogin.classList.add("active"); tabRegister.classList.remove("active"); usernameFieldGroup.classList.add("hidden"); authSubmitBtn.textContent = "Log In"; } } authForm.addEventListener("submit", async (e) => { e.preventDefault(); authError.textContent = ""; const email = authEmail.value.trim(); const password = authPassword.value.trim(); if (isRegistering) { const username = authUsername.value.trim().toLowerCase(); if (!username) { authError.textContent = "Username is required."; return; } const { data, error } = await supabaseClient.auth.signUp({ email, password, options: { data: { username, display_name: username } } }); if (error) { authError.textContent = error.message; return; } if (data.user) { // Sync initial profile await supabaseClient.from("users").upsert({ id: data.user.id, username: username, display_name: username }); initUserSession(data.user); } } else { const { data, error } = await supabaseClient.auth.signInWithPassword({ email, password }); if (error) { authError.textContent = error.message; return; } initUserSession(data.user); } }); async function initUserSession(user) { currentUser = user; // Fetch full user profile const { data: profile } = await supabaseClient .from("users") .select("*") .eq("id", user.id) .single(); currentProfile = profile || { id: user.id, username: user.user_metadata?.username || user.email.split("@")[0], display_name: user.user_metadata?.display_name || user.email.split("@")[0] }; authScreen.classList.add("hidden"); appMount.classList.remove("hidden"); updateUserPanel(); loadFriendsList(); setupRealtimeMessages(); } // ========================================== // 4. NAVIGATION & VIEWS // ========================================== navFriends.addEventListener("click", () => { navFriends.classList.add("active"); navNitro.classList.remove("active"); chatView.classList.remove("hidden"); nitroView.classList.add("hidden"); }); navNitro.addEventListener("click", () => { navNitro.classList.add("active"); navFriends.classList.remove("active"); nitroView.classList.remove("hidden"); chatView.classList.add("hidden"); }); // Settings Modal Tabs document.querySelectorAll(".settings-tab[data-tab]").forEach(tab => { tab.addEventListener("click", (e) => { document.querySelectorAll(".settings-tab[data-tab]").forEach(t => t.classList.remove("active")); e.target.classList.add("active"); const targetTab = e.target.getAttribute("data-tab"); if (targetTab === "profile") { document.getElementById("tabContentProfile").classList.remove("hidden"); document.getElementById("tabContentAppearance").classList.add("hidden"); } else if (targetTab === "appearance") { document.getElementById("tabContentAppearance").classList.remove("hidden"); document.getElementById("tabContentProfile").classList.add("hidden"); } }); }); openSettingsBtn.addEventListener("click", () => { populateProfileForm(); settingsModal.classList.remove("hidden"); }); closeSettingsBtn.addEventListener("click", () => settingsModal.classList.add("hidden")); document.getElementById("logoutBtn").addEventListener("click", async () => { await supabaseClient.auth.signOut(); window.location.reload(); }); // ========================================== // 5. FRIENDS & DIRECT MESSAGES // ========================================== openAddFriendModal.addEventListener("click", () => addFriendModal.classList.remove("hidden")); closeAddFriendBtn.addEventListener("click", () => addFriendModal.classList.add("hidden")); submitAddFriendBtn.addEventListener("click", async () => { addFriendError.textContent = ""; const username = addFriendUsername.value.trim().toLowerCase(); const { data: targetUser } = await supabaseClient .from("users") .select("*") .eq("username", username) .single(); if (!targetUser) { addFriendError.textContent = "User not found."; return; } // Insert friend relationships await supabaseClient.from("friends").insert([ { user_id: currentUser.id, friend_id: targetUser.id }, { user_id: targetUser.id, friend_id: currentUser.id } ]); addFriendModal.classList.add("hidden"); addFriendUsername.value = ""; loadFriendsList(); }); async function loadFriendsList() { const { data: friends } = await supabaseClient .from("friends") .select("friend_id, users!friends_friend_id_fkey(*)") .eq("user_id", currentUser.id); friendsList.innerHTML = ""; if (!friends || friends.length === 0) { friendsList.innerHTML = `